package org.ricks.net.action.context.session.modular;

import org.ricks.net.transport.AioSession;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 模块 session管理
 */
public class ModularContext implements NodeStateListener {

    private ModularContext() {
    }

    public static ModularContext me() {
        return ModularContext.Holder.ME;
    }

    /** 通过 JVM 的类加载机制, 保证只加载一次 (singleton) */
    private static class Holder {
        static final ModularContext ME = new ModularContext();
    }


    /**
     * cmd - 模块ID 映射关系，k=cmd v=modularId
     */
    private final ConcurrentMap<Short, Short> cmdToModuleMap = new ConcurrentHashMap<>();
    /**
     * k=modularId    模块ID
     * v=socket session  模块都是集群模式
     */
    private final ConcurrentMap<Short, List<AioSession>> moduleSessions = new ConcurrentHashMap<>();


    public void registerCommand(short cmd, short modularId) {
        Short existing = cmdToModuleMap.putIfAbsent(cmd, modularId);
        if (existing != null && existing != modularId) {
            throw new IllegalStateException("Command conflict: " + cmd +
                    " already registered to module " + existing);
        }
    }

    @Override
    public void onNodeAdded(AioSession session, short moduleId) {
        moduleSessions.compute(moduleId, (k, sessions) -> {
            if (sessions == null) {
                sessions = new CopyOnWriteArrayList<>();
            }
            if (!sessions.contains(session)) {
                sessions.add(session);
            }
            return sessions;
        });
    }

    @Override
    public void onNodeRemoved(AioSession session, short moduleId) {
        moduleSessions.computeIfPresent(moduleId, (k, sessions) -> {
            sessions.remove(session);
            return sessions.isEmpty() ? null : sessions;
        });
    }
}
